﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using WpfChartingControlLibrary.Common;
using System.Collections.ObjectModel;
using System.Windows.Media.Animation;
using System.Windows.Controls.Primitives;
using System.Printing;
using System.Collections;

namespace WpfChartingControlLibrary.PieChart
{
    /// <summary>
    /// Follow steps 1a or 1b and then 2 to use this custom control in a XAML file.
    ///
    /// Step 1a) Using this custom control in a XAML file that exists in the current project.
    /// Add this XmlNamespace attribute to the root element of the markup file where it is 
    /// to be used:
    ///
    ///     xmlns:MyNamespace="clr-namespace:WpfChartingControlLibrary.LineCharts"
    ///
    ///
    /// Step 1b) Using this custom control in a XAML file that exists in a different project.
    /// Add this XmlNamespace attribute to the root element of the markup file where it is 
    /// to be used:
    ///
    ///     xmlns:MyNamespace="clr-namespace:WpfChartingControlLibrary.LineCharts;assembly=WpfChartingControlLibrary.LineCharts"
    ///
    /// You will also need to add a project reference from the project where the XAML file lives
    /// to this project and Rebuild to avoid compilation errors:
    ///
    ///     Right click on the target project in the Solution Explorer and
    ///     "Add Reference"->"Projects"->[Browse to and select this project]
    ///
    ///
    /// Step 2)
    /// Go ahead and use your control in the XAML file.
    ///
    ///     <MyNamespace:PieChartControl/>
    ///
    /// </summary>
    /// 
    [TemplatePart(Name = "PART_ChartGrid", Type = typeof(Grid))]
    [TemplatePart(Name = "PART_Legend", Type = typeof(ItemsControl))]
    [TemplateVisualState(Name = "Selected", GroupName = "SelectionStates")]

    public class PieChartControl : ListBox, IWeakEventListener
    {

        #region("Dependency properties")

        public static DependencyProperty DataListProperty = DependencyProperty.Register("DataListProperty", typeof(ObservableCollection<ChartingModel.Collections.PieChartDataList>), typeof(PieChartControl));

        public static DependencyProperty DataListAutoUpdateProperty = DependencyProperty.Register("DataListAutoUpdateProperty", typeof(bool), typeof(PieChartControl));

    //    public static DependencyProperty SelectedItemProperty = DependencyProperty.Register("SelectedItemProperty", typeof(ObservableCollection<ChartingModel.Collections.PieChartDataList>), typeof(PieChartControl));
        
        
        
        public static DependencyProperty ChartStyleProperty = DependencyProperty.Register("ChartStyleProperty", typeof(ChartingModel.Style.PieChartStyle), typeof(PieChartControl));


        #endregion


        #region("Public Property Wrappers")

        private new IEnumerable ItemsSource
        { get; set; }

        public ObservableCollection<ChartingModel.Collections.PieChartDataList> DataList
        {
            get { return (ObservableCollection<ChartingModel.Collections.PieChartDataList>)GetValue(DataListProperty); }
            set { SetValue(DataListProperty, value); }
        }

        public bool DataListAutoUpdate
        {
            get { return (bool)GetValue(DataListAutoUpdateProperty); }
            set { SetValue(DataListAutoUpdateProperty, value); }
        }


        public ChartingModel.Style.PieChartStyle ChartStyle
        {
            get { return (ChartingModel.Style.PieChartStyle)GetValue(ChartStyleProperty); }
            set { SetValue(ChartStyleProperty, value); }
        }

        #endregion

        #region("Contructors")
        static PieChartControl()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(PieChartControl), new FrameworkPropertyMetadata(typeof(PieChartControl)));
            CommandManager.RegisterClassCommandBinding(typeof(PieChartControl), new CommandBinding(ApplicationCommands.Print, PrintCommand_Executed));
        }

        public PieChartControl()
        {
            pc = new ChartingModel.Style.PieChartStyle();
            this.DataList = new ObservableCollection<ChartingModel.Collections.PieChartDataList>();
            base.ItemsSource = this.DataList;
            this.DataListAutoUpdate = true;
        }

        #endregion

        /// <summary>
        /// used to print the graph
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void PrintCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            PieChartControl chart = sender as PieChartControl;
            PrintDialog printDlg = new System.Windows.Controls.PrintDialog();

            if (printDlg.ShowDialog() == true)
            {

                try
                {
                    //get the size of the printer page 
                    PrintCapabilities capabilities = printDlg.PrintQueue.GetPrintCapabilities(printDlg.PrintTicket);
                    double pageMargin = Math.Min(capabilities.PageImageableArea.OriginWidth, capabilities.PageImageableArea.OriginHeight);
                    double additionalMargin = Math.Max(0, pageMargin + 5);
                    Size pageSize = new Size(capabilities.PageImageableArea.ExtentWidth - additionalMargin * 2, capabilities.PageImageableArea.ExtentHeight - additionalMargin * 2);
                    //get scale of the print wrt to screen of WPF visual 
                    double scale = Math.Min(pageSize.Width / chart.ActualWidth, pageSize.Height / chart.ActualHeight);
                    Size printSize = new Size(chart.ActualWidth * scale, chart.ActualHeight * scale);
                    Point upperLeft = new Point(capabilities.PageImageableArea.OriginWidth + additionalMargin, capabilities.PageImageableArea.OriginHeight + additionalMargin);
                    //Transform the Visual to scale 
                    chart.LayoutTransform = new ScaleTransform(scale, scale); chart.Measure(printSize); chart.Arrange(new Rect(upperLeft, printSize));
                    printDlg.PrintVisual(chart, "Test");
                }
                catch (System.Printing.PrintQueueException)
                {

                }
                catch (System.Printing.PrintSystemException)
                { }

                chart.LayoutTransform = null;
            }






            //PrintDialog printDialog = new PrintDialog();
            //if (printDialog.ShowDialog() == true)
            //{
            //    //get selected printer capabilities
            //    System.Printing.PrintCapabilities capabilities = printDialog.PrintQueue.GetPrintCapabilities(printDialog.PrintTicket);

            //    //get scale of the print wrt to screen of WPF visual
            //    double scale = Math.Min(capabilities.PageImageableArea.ExtentWidth / barChart.ActualWidth, capabilities.PageImageableArea.ExtentHeight / barChart.ActualHeight);

            //    //Transform the Visual to scale
            //    barChart.LayoutTransform = new ScaleTransform(scale, scale);


            //    //get the size of the printer page

            //    Size sz = new Size(capabilities.PageImageableArea.ExtentWidth, capabilities.PageImageableArea.ExtentHeight);

            //    //update the layout of the visual to the printer page size.

            //    barChart.Measure(sz);

            //    barChart.Arrange(new Rect(new Point(capabilities.PageImageableArea.OriginWidth, capabilities.PageImageableArea.OriginHeight), sz));

            //    //now print the visual to printer to fit on the one page.

            //    printDialog.PrintVisual(barChart, "First Fit to Page WPF Print");

            //    barChart.LayoutTransform = null;
            //}
        }


        /// <summary>
        /// set focus to the graph control so printing command is activated from ctrl+P
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseDown(MouseButtonEventArgs e)
        {
            base.OnMouseDown(e);
            if (this.IsEnabled && !this.IsFocused)
            {
                this.Focus();
            }
        }

        
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            _chartGrid = GetTemplateChild("PART_ChartGrid") as Grid;
            _chartItemsControl = GetTemplateChild("PART_ChartItemsControl") as ListBox;
       //     _chartItemsControl.SourceUpdated += _chartItemsControl_SourceUpdated;
            _chartItemsControl.SelectionChanged += _chartItemsControl_SelectionChanged;

            GridSizeChangedEventManager.AddListener(_chartGrid, this);
        }

        /// <summary>
        /// prevent subscribers from receiving the event 2 times
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void _chartItemsControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
      //      base.OnSelectionChanged(e);
            e.Handled = true;
        }

        protected override void OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            base.OnItemsChanged(e);
            if (this.DataListAutoUpdate)
            {
                this.AddChart();
            }
        
        }

        public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
        {
            if (managerType == typeof(GridSizeChangedEventManager))
            {
                GridSizeChanged(_chartGrid, (SizeChangedEventArgs)e);
            }
            else
            {
                return false;       // unrecognized event
            }
            return true;
        }

        public void GridSizeChanged(object sender, SizeChangedEventArgs e)
        {
            double width = _chartGrid.ActualWidth;
            double height = _chartGrid.ActualHeight;
            double side = width;
            if (width > height)
            {
                side = height;
            }
            _chartItemsControl.Width = side;
            _chartItemsControl.Height = side;
            pc.AddPie(this._chartItemsControl.Width, this._chartItemsControl.Height);

        }

        ChartingModel.Style.PieChartStyle pc;

        public void AddChart()
        {
            pc.AddDataList(DataList);
            if (this._chartItemsControl != null)
            {
                pc.AddPie(this._chartItemsControl.Width, this._chartItemsControl.Height);                
            }


        }

        ListBox _chartItemsControl;
        Grid _chartGrid;
    }
}


